using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Web;
using System.Xml;
using IEMSOFT.Foundation.Security;
using IEMSOFT.Foundation;
namespace IEMSOFT.Foundation.Payment.Weixin
{

    public class ResponseHandler
    {

        private string _partnerKey;

        private string appkey; //paysignkey
        //xmlMap
        private Hashtable xmlMap;

        protected Hashtable parameters;

        private string debugInfo;

        private static string SignField = "appid,appkey,timestamp,openid,noncestr,issubscribe";

        public string XmlBody { get; set; }

        public string OutTradeNo
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("out_trade_no"))
                {
                    ret = parameters["out_trade_no"].ToString();
                }
                return ret;
            }
        }
        public string SignType
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("sign_type"))
                {
                    ret = parameters["sign_type"].ToString();
                }
                return ret;
            }
        }
        public string InputCharset
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("input_charset"))
                {
                    ret = parameters["input_charset"].ToString();
                }
                return ret;
            }
        }
        public string Sign
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("sign"))
                {
                    ret = parameters["sign"].ToString();
                }
                return ret;
            }
        }
        public int TradeMode
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("trade_mode"))
                {
                    ret = parameters["trade_mode"].ToString();
                }
                return ret.ToInt();
            }
        }
        public int TradeState
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("trade_state"))
                {
                    ret = parameters["trade_state"].ToString();
                }
                return ret.ToInt();
            }
        }
        public string BankType
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("bank_type"))
                {
                    ret = parameters["bank_type"].ToString();
                }
                return ret.ToString();
            }
        }
        public string BankBillno
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("bank_billno"))
                {
                    ret = parameters["bank_billno"].ToString();
                }
                return ret.ToString();
            }
        }
        public int TotalFee
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("total_fee"))
                {
                    ret = parameters["total_fee"].ToString();
                }
                return ret.ToInt();
            }
        }

        public int FeeType
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("fee_type"))
                {
                    ret = parameters["fee_type"].ToString();
                }
                return ret.ToInt();
            }
        }
        public string NotifyId
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("notify_id"))
                {
                    ret = parameters["notify_id"].ToString();
                }
                return ret;
            }
        }
        public string TransactionId
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("transaction_id"))
                {
                    ret = parameters["transaction_id"].ToString();
                }
                return ret;
            }
        }
        public string TimeEnd
        {
            get
            {
                var ret = string.Empty;
                if (parameters.Contains("time_end"))
                {
                    ret = parameters["time_end"].ToString();
                }
                return ret;
            }
        }
        public string TimeStampStr
        {
            get
            {
                var ret = string.Empty;
                if (xmlMap.Contains("TimeStamp"))
                {
                    ret = xmlMap["TimeStamp"].ToString();
                }
                return ret;
            }
        }
        public string NonceStr
        {
            get
            {
                var ret = string.Empty;
                if (xmlMap.Contains("NonceStr"))
                {
                    ret = xmlMap["NonceStr"].ToString();
                }
                return ret;
            }
        }
        public string OpenId
        {
            get
            {
                var ret = string.Empty;
                if (xmlMap.Contains("OpenId"))
                {
                    ret = xmlMap["OpenId"].ToString();
                }
                return ret;
            }
        }
        public string AppSignature
        {
            get
            {
                var ret = string.Empty;
                if (xmlMap.Contains("AppSignature"))
                {
                    ret = xmlMap["AppSignature"].ToString();
                }
                return ret;
            }
        }
        public string IsSubscribe
        {
            get
            {
                var ret = string.Empty;
                if (xmlMap.Contains("IsSubscribe"))
                {
                    ret = xmlMap["IsSubscribe"].ToString();
                }
                return ret;
            }
        }

        public ResponseHandler(HttpContext httpContext)
        {
            parameters = new Hashtable();
            xmlMap = new Hashtable();
            var currentRequest = httpContext.Request;
            NameValueCollection collection;
            //post data
            if (currentRequest.HttpMethod == "POST")
            {
                collection = currentRequest.Form;
                foreach (string k in collection)
                {
                    string v = (string)collection[k];
                    this.setParameter(k, v);
                }
            }
            //query string
            collection = currentRequest.QueryString;
            foreach (string k in collection)
            {
                string v = (string)collection[k];
                this.setParameter(k, v);
            }
            if (currentRequest.InputStream.Length > 0)
            {
                try
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(currentRequest.InputStream);
                    XmlNode root = xmlDoc.SelectSingleNode("xml");
                    XmlNodeList xnl = root.ChildNodes;
                    XmlBody = xmlDoc.OuterXml;
                    foreach (XmlNode xnf in xnl)
                    {
                        xmlMap.Add(xnf.Name, xnf.InnerText);
                    }
                }
                catch (Exception)
                {
                    currentRequest.InputStream.Position = 0;
                    byte[] bytes = new byte[currentRequest.InputStream.Length];
                    currentRequest.InputStream.ReadAsync(bytes, 0, bytes.Length).Wait();
                    var str = httpContext.Request.ContentEncoding.GetString(bytes);
                    XmlBody = str;
                }
             
            }
        }


        public string getPaprtnerKey()
        { return _partnerKey; }

        public void setKey(string partnerKey, string appkey)
        {
            this._partnerKey = partnerKey;
            this.appkey = appkey;
        }

        public string getParameter(string parameter)
        {
            string s = (string)parameters[parameter];
            return (null == s) ? "" : s;
        }

        public void setParameter(string parameter, string parameterValue)
        {
            if (parameter != null && parameter != "")
            {
                if (parameters.Contains(parameter))
                {
                    parameters.Remove(parameter);
                }

                parameters.Add(parameter, parameterValue);
            }
        }

        public virtual Boolean isTenpaySign()
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            sb.Append("key=" + this.getPaprtnerKey());
            string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToLower();
            this.setDebugInfo(sb.ToString() + " => sign:" + sign);
            return getParameter("sign").ToLower().Equals(sign);
        }

        public virtual Boolean isWXsign()
        {
            StringBuilder sb = new StringBuilder();
            Hashtable signMap = new Hashtable();

            foreach (string k in xmlMap.Keys)
            {
                if (k != "SignMethod" && k != "AppSignature")
                {
                    signMap.Add(k.ToLower(), xmlMap[k]);
                }
            }
            signMap.Add("appkey", this.appkey);


            ArrayList akeys = new ArrayList(signMap.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)signMap[k];
                if (sb.Length == 0)
                {
                    sb.Append(k + "=" + v);
                }
                else
                {
                    sb.Append("&" + k + "=" + v);
                }
            }

            string sign = SHA1Util.getSha1(sb.ToString(), getCharset()).ToString().ToLower();

            this.setDebugInfo(sb.ToString() + " => SHA1 sign:" + sign);

            return sign.Equals(xmlMap["AppSignature"]);

        }

        public virtual Boolean isWXsignfeedback()
        {
            StringBuilder sb = new StringBuilder();
            Hashtable signMap = new Hashtable();

            foreach (string k in xmlMap.Keys)
            {
                if (SignField.IndexOf(k.ToLower()) != -1)
                {
                    signMap.Add(k.ToLower(), xmlMap[k]);
                }
            }
            signMap.Add("appkey", this.appkey);


            ArrayList akeys = new ArrayList(signMap.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)signMap[k];
                if (sb.Length == 0)
                {
                    sb.Append(k + "=" + v);
                }
                else
                {
                    sb.Append("&" + k + "=" + v);
                }
            }

            string sign = SHA1Util.getSha1(sb.ToString(), getCharset()).ToString().ToLower();

            this.setDebugInfo(sb.ToString() + " => SHA1 sign:" + sign);

            return sign.Equals(xmlMap["AppSignature"]);

        }

        public string getDebugInfo()
        { return debugInfo; }

        protected void setDebugInfo(String debugInfo)
        { this.debugInfo = debugInfo; }

        private string _charset = "UTF-8";
        public virtual void setCharset(string value)
        {
            _charset = value;
        }

        public virtual string getCharset()
        {
            return _charset;
        }

    }
}
